home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJLSR106.ARJ / FNMATCH.C < prev    next >
C/C++ Source or Header  |  1992-03-02  |  4KB  |  138 lines

  1. /* This is file FNMATCH.C */
  2. /* This file may have been modified by DJ Delorie (Jan 1991).  If so,
  3. ** these modifications are Coyright (C) 1991 DJ Delorie, 24 Kirsten Ave,
  4. ** Rochester NH, 03867-2954, USA.
  5. */
  6.  
  7. /*
  8.  * Copyright (c) 1989 The Regents of the University of California.
  9.  * All rights reserved.
  10.  *
  11.  * This code is derived from software contributed to Berkeley by
  12.  * Guido van Rossum.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. #if defined(LIBC_SCCS) && !defined(lint)
  30. static char sccsid[] = "@(#)fnmatch.c    5.3 (Berkeley) 6/23/90";
  31. #endif /* LIBC_SCCS and not lint */
  32.  
  33. /*
  34.  * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9).
  35.  * Compares a filename or pathname to a pattern.
  36.  */
  37.  
  38. #include <unistd.h>
  39. #include <string.h>
  40.  
  41. #define    EOS    '\0'
  42.  
  43. static char *
  44. rangematch(pattern, test)
  45.     register char *pattern, test;
  46. {
  47.     register char c, c2;
  48.     int negate, ok;
  49.  
  50.     if (negate = (*pattern == '!'))
  51.         ++pattern;
  52.  
  53.     /*
  54.      * TO DO: quoting
  55.      */
  56.  
  57.     for (ok = 0; (c = *pattern++) != ']';) {
  58.         if (c == EOS)
  59.             return(NULL);        /* illegal pattern */
  60.         if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
  61.             if (c <= test && test <= c2)
  62.                 ok = 1;
  63.             pattern += 2;
  64.         }
  65.         else if (c == test)
  66.             ok = 1;
  67.     }
  68.     return(ok == negate ? NULL : pattern);
  69. }
  70.  
  71. fnmatch(pattern, string, flags)
  72.     register char *pattern, *string;
  73.     int flags;
  74. {
  75.     register char c;
  76.     char test, *rangematch();
  77.  
  78.     for (;;)
  79.         switch (c = *pattern++) {
  80.         case EOS:
  81.             return(*string == EOS);
  82.         case '?':
  83.             if ((test = *string++) == EOS ||
  84.                 test == '/' && flags & FNM_PATHNAME)
  85.                 return(0);
  86.             break;
  87.         case '*':
  88.             c = *pattern;
  89.             /* collapse multiple stars */
  90.             while (c == '*')
  91.                 c = *++pattern;
  92.  
  93.             /* optimize for pattern with * at end or before / */
  94.             if (c == EOS)
  95.                 if (flags & FNM_PATHNAME)
  96.                     return(!index(string, '/'));
  97.                 else
  98.                     return(1);
  99.             else if (c == '/' && flags & FNM_PATHNAME) {
  100.                 if ((string = index(string, '/')) == NULL)
  101.                     return(0);
  102.                 break;
  103.             }
  104.  
  105.             /* general case, use recursion */
  106.             while ((test = *string) != EOS) {
  107.                 if (fnmatch(pattern, string, flags))
  108.                     return(1);
  109.                 if (test == '/' && flags & FNM_PATHNAME)
  110.                     break;
  111.                 ++string;
  112.             }
  113.             return(0);
  114.         case '[':
  115.             if ((test = *string++) == EOS ||
  116.                 test == '/' && flags & FNM_PATHNAME)
  117.                 return(0);
  118.             if ((pattern = rangematch(pattern, test)) == NULL)
  119.                 return(0);
  120.             break;
  121.         case '\\':
  122.             if (flags & FNM_QUOTE) {
  123.                 if ((c = *pattern++) == EOS) {
  124.                     c = '\\';
  125.                     --pattern;
  126.                 }
  127.                 if (c != *string++)
  128.                     return(0);
  129.                 break;
  130.             }
  131.             /* FALLTHROUGH */
  132.         default:
  133.             if (c != *string++)
  134.                 return(0);
  135.             break;
  136.         }
  137. }
  138.